package com.example.myapplication.utils

import android.net.Uri
import android.text.TextUtils
import com.example.myapplication.network.LaunchInfo
import com.example.myapplication.ui.VideoItem
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import com.tencent.mmkv.MMKV
import kotlin.reflect.KClass

object SPUtils {
    const val DEFAULT_ID = "app"

    private fun getMMKId(useDefaultId: Boolean = false): String {
        if (useDefaultId) {
            return DEFAULT_ID
        }
        return DEFAULT_ID
    }

    /**
     * 设置保存key value
     *
     * @param key
     * @param value
     * @param useDefaultId
     */
    fun setKeyValue(key: String, value: Boolean, useDefaultId: Boolean = false) {
        val kv = MMKV.mmkvWithID(getMMKId(useDefaultId))
        kv.encode(key, value)
    }

    /**
     * 设置保存key value
     *
     * @param key
     * @param value
     */
    fun setKeyValue(key: String, value: String) {
        val kv = MMKV.mmkvWithID(getMMKId())
        kv.encode(key, value)
    }

    /**
     * Get string value by key
     *
     * @param key
     * @return
     */
    fun getStringValue(key: String): String {
        val kv = MMKV.mmkvWithID(getMMKId())
        return kv.decodeString(key, "")!!
    }

    /**
     * Get boolean value by key
     *
     * @param key
     * @return
     */
    fun getBooleanValue(key: String, useDefaultId: Boolean = false): Boolean {
        val kv = MMKV.mmkvWithID(getMMKId(useDefaultId))
        return kv.decodeBool(key, false)
    }

    fun getStringList(key: String): List<String> {
        val kv = MMKV.mmkvWithID(getMMKId())
        val value = kv.decodeString(key)
        return if (TextUtils.isEmpty(value)) {
            emptyList()
        } else {
            val type = object : TypeToken<List<String>>() {}.type
            getGson().fromJson(value, type)
        }
    }

    /**
     * 保存对象
     *
     * @param T
     * @param key
     * @param value
     */
    fun <T> setKeyValue(key: String, value: T?) {
        val kv = MMKV.mmkvWithID(getMMKId())
        if (value == null) {
            kv.encode(key, "")
        } else {
            kv.encode(key, getGson().toJson(value))
        }
    }

    /**
     * 根据key获取对像
     *
     * @param T
     * @param key
     * @return
     */
    fun <T : Any> getByKey(key: String, t: KClass<T>): T? {
        val kv = MMKV.mmkvWithID(getMMKId())
        val value = kv.decodeString(key)
        return if (TextUtils.isEmpty(value)) {
            null
        } else {
            getGson().fromJson(value, t.java)
        }
    }

    fun getHistory(): List<VideoItem> {
        val kv = MMKV.mmkvWithID(getMMKId())
        val value = kv.decodeString("video_history")
        return if (TextUtils.isEmpty(value)) {
            emptyList()
        } else {
            val type = object : TypeToken<List<VideoItem>>() {}.type
            getGson().fromJson(value, type)
        }
    }

    fun setHistory(data: VideoItem) {
        if (isHistory(data.id)) {
            setKeyValue("video_history", getHistory().filter { it.id != data.id })
        } else {
            setKeyValue("video_history", getHistory().plus(data))
        }
    }

    fun isHistory(id: String?): Boolean {
        if (id == null) return false
        getHistory().forEach {
            if (it.id == id) {
                return true
            }
        }
        return false
    }

    fun delHistory(): Boolean {
        setKeyValue("video_history", "")
        return true
    }

    fun delHistoryById(id: String): Boolean {
        setKeyValue("video_history", getHistory().filter { it.id != id })
        return true
    }

    fun getCollects(): List<VideoItem> {
        val kv = MMKV.mmkvWithID(getMMKId())
        val value = kv.decodeString("video_collect")
        return if (TextUtils.isEmpty(value)) {
            emptyList()
        } else {
            val type = object : TypeToken<List<VideoItem>>() {}.type
            getGson().fromJson(value, type)
        }
    }

    private fun getGson(): Gson {
        val gson = GsonBuilder()
            .registerTypeAdapter(Uri::class.java, UriAdapter())
            .create()
        return gson
    }

    fun setCollect(data: VideoItem) {
        if (isCollected(data.id)) {
            setKeyValue("video_collect", getCollects().filter { it.id != data.id })
        } else {
            setKeyValue("video_collect", getCollects().plus(data))
        }
    }

    fun isCollected(id: String?): Boolean {
        if (id == null) return false
        getCollects().forEach {
            if (it.id == id) {
                return true
            }
        }
        return false
    }

    fun delCollected(): Boolean {
        setKeyValue("video_collect", "")
        return true
    }

    fun getKeywords(): List<String> {
        return getStringList("keywords")
    }

    fun setKeywords(value: String) {
        if (value.isEmpty()) {
            return
        }
        var kws = getKeywords().let {
            if (it.contains(value)) {
                return
            }
            it.plus(value)
        }.reversed()
        setKeyValue("keywords", kws)
    }

    fun getDevOaid(): String {
        var oaid = getStringValue("oaid")
        oaid = oaid.replace("\"", "")
        if (oaid.isEmpty()) {
            oaid = "12345678911111"
        }
        return oaid
    }

    fun setAdData(data: LaunchInfo) {
        setKeyValue("ad_data", data)
    }

    fun getAdData(): LaunchInfo? {
        val kv = MMKV.mmkvWithID(getMMKId())
        val value = kv.decodeString("ad_data")
        return if (TextUtils.isEmpty(value)) {
            null
        } else {
            getGson().fromJson(value, LaunchInfo::class.java)
        }
    }

    fun saveRuleTime(rule: MutableMap<String, Long>) {
        setKeyValue("ad_show_rule", rule)
    }

    fun getRuleTime(): MutableMap<String, Long> {
        val kv = MMKV.mmkvWithID(getMMKId())
        val value = kv.decodeString("ad_show_rule")
        return if (TextUtils.isEmpty(value)) {
            mutableMapOf()
        } else {
            val type = object : TypeToken<MutableMap<String, Long>>() {}.type
            Gson().fromJson(value, type)
        }
    }

    fun hasPrivacy(): Boolean {
        return getBooleanValue("has_privacy")
    }

    fun setPrivacy(has: Boolean) {
        setKeyValue("has_privacy", has)
    }
}